package com.hcc.gateway.netty.filter;

import com.hcc.gateway.netty.context.GatewayExchange;
import com.hcc.gateway.netty.context.ReqContext;
import com.hcc.gateway.netty.support.ByteBufUtils;
import com.hcc.gateway.netty.support.GatewayConstants;
import com.hcc.gateway.netty.support.GatewayResponse;
import io.netty.handler.codec.http.HttpMethod;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import okhttp3.Call;
import okhttp3.Headers;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import org.springframework.stereotype.Component;

import java.net.URI;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.IntStream;

/**
 * HttpRoutingFilter
 *
 * @author shengjun.hu
 * @date 2021/12/28
 */
@Slf4j
@Component
public class HttpRoutingFilter implements GatewayFilter {

    @Override
    public int getOrder() {
        return GatewayConstants.ORDER + 2;
    }

    @SneakyThrows
    @Override
    public void filter(GatewayExchange exchange, GatewayFilterChain chain) {
        log.info("进入HttpRoutingFilter !");

        ReqContext reqContext = exchange.getReqContext();
        URI uri = exchange.getAttributeByName(GatewayConstants.GATEWAY_REQUEST_URI_ATTR, URI.class);
        if (!isHttpRequest(uri.getScheme().toLowerCase())) {
            throw new RuntimeException("仅支持http协议！");
        }

        OkHttpClient okHttpClient = new OkHttpClient();
        Request.Builder builder = new Request.Builder().url(uri.toString());
        if (HttpMethod.GET.equals(reqContext.getMethod())) {
            builder.get();
        } else if (HttpMethod.POST.equals(reqContext.getMethod())) {
            RequestBody requestBody = RequestBody.create(null, ByteBufUtils.readByteFromByteBuf(reqContext.getContent()));
            builder.post(requestBody);
        }

        Call call = okHttpClient.newCall(builder.build());
        try (Response response = call.execute()) {
            if (response.isSuccessful()) {
                Headers headers = response.headers();
                GatewayResponse gatewayResponse = new GatewayResponse();
                gatewayResponse.setHttpCode(response.code());
                Map<String, String> map = new HashMap<>();
                IntStream.range(0, headers.size()).forEach(i -> map.put(headers.name(i), headers.value(i)));
                gatewayResponse.setHeaders(map);
                if (response.body() != null) {
                    gatewayResponse.setBody(response.body().bytes());
                }
                exchange.addAttribute(GatewayConstants.GATEWAY_RESPONSE_ATTR, gatewayResponse);
            }
        } catch (Exception e) {
            throw new RuntimeException(String.format("请求地址：[%s]失败！", reqContext.getUri()), e);
        }

        chain.filter(exchange);
    }

    private boolean isHttpRequest(String scheme) {
        return "http".equals(scheme) || "https".equals(scheme);
    }

}
